#pragma once
#include "Mode.h"
#include "crypto/algorithms/digest/GHash.h"
#include "crypto/keys/FAQSecretKey.h"
#include "io/ByteArrayOutputStream.h"
namespace yzrilyzr_crypto{
	//TODO
	ECLASS(GCM, public Mode){
	private:
	yzrilyzr_array::ByteArray iv;
	yzrilyzr_array::ByteArray aad;//附加身份验证数据
	u_index tagLength=0;
	yzrilyzr_io::ByteArrayOutputStream buffer;
	yzrilyzr_array::ByteArray J0; // 初始计数器
	yzrilyzr_array::ByteArray Y_Inc_Cache; // 初始计数器
	GHash ghash;
	bool initialized=false;
	public:
	GCM(const yzrilyzr_array::ByteArray & iv, const yzrilyzr_array::ByteArray & aad, u_index tagLength);
	void init(FAQCipherAlgorithm & algorithm);
	private:
	yzrilyzr_array::ByteArray padBlock(const yzrilyzr_array::ByteArray & input, u_index blockSize);
	public:
	yzrilyzr_array::ByteArray encrypt(const yzrilyzr_array::ByteArray & block, FAQCipherAlgorithm & algorithm)override;
	yzrilyzr_array::ByteArray encryptFinal(const yzrilyzr_array::ByteArray & block, FAQCipherAlgorithm & algorithm)override;
	yzrilyzr_array::ByteArray decrypt(const yzrilyzr_array::ByteArray & block, FAQCipherAlgorithm & algorithm)override;
	yzrilyzr_array::ByteArray decryptFinal(const yzrilyzr_array::ByteArray & block, FAQCipherAlgorithm & algorithm)override;
	void copyCounterToCache();
	static yzrilyzr_array::ByteArray increment32ToThis(yzrilyzr_array::ByteArray value);
	static yzrilyzr_array::ByteArray GCTR(FAQCipherAlgorithm & algorithm, yzrilyzr_array::ByteArray & ctr, yzrilyzr_array::ByteArray & input);
	private:
	void checkInitialized();
	public:
	GHash & getGHash();
	};
}